package server;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;

import common.Encrypt;
import common.TextMessage;

/**
 * class for an individual connection to a client. allows to send messages to
 * this client and handles incoming messages.
 */
public class Connection extends Thread {
    protected Socket socket;
    protected ObjectInputStream inputStream;
    protected ObjectOutputStream outputStream;
    private Server server;
    private boolean auth = false;
    private static final String key = "SPLisAwesome";

    public Connection(Socket s, Server server) {
        this.socket = s;
        try {
            inputStream = new ObjectInputStream((s.getInputStream()));
            outputStream = new ObjectOutputStream((s.getOutputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.server = server;
    }

    /**
     * waits for incoming messages from the socket
     */
    public void run() {
        String clientName = socket.getInetAddress().toString();
        try {
            Object msg = null;
            while (((msg = inputStream.readObject()) != null) && !auth) {
                handleIncomingMessage(clientName, msg);
                if (auth) {
                    break;
                }
            }
            runAuthenticated(clientName);
        } catch (SocketException e) {
        } catch (EOFException e) {
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            server.removeConnection(this);
            if (auth) {
                server.broadcast(clientName + " has left.");
            }
            try {
                socket.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }

    private void runAuthenticated(String clientName) throws IOException, ClassNotFoundException {
            server.broadcast(clientName + " has joined.");
            Object msg = null;
            while ((msg = inputStream.readObject()) != null) {
                handleIncomingMessage(clientName, msg);
            }
    }

    /**
     * decides what to do with incoming messages
     *
     * @param name
     *            name of the client
     * @param msg
     *            received message
     */
    private void handleIncomingMessage(String name, Object msg) {
        if (msg instanceof TextMessage)
            if (auth) {
                server.broadcast(name + " - " + (Encrypt.encrypt((TextMessage) msg)).getContent());
            } else if (Encrypt.encrypt(((TextMessage) msg)).getContent().equals(key)){
               auth = true;
            } else {
                send("Wrong Password");
            }

    }

    /**
     * sends a message to the client
     *
     * @param line
     *            text of the message
     */
    public void send(String line) {
        TextMessage msg = new TextMessage(line);
        send(Encrypt.encrypt(msg));
    }

    public void send(TextMessage msg) {
        try {
            synchronized (outputStream) {
                outputStream.writeObject(msg);
            }
            outputStream.flush();
        } catch (IOException ex) {
        }
    }
}
